#!/usr/bin/env python
# -*- coding: utf-8 -*-

from typing import Optional
import transaction
# 导入ZODB相关模块
from ZODB import FileStorage, DB
from ZEO.ClientStorage import ClientStorage
from common.utils import LogUtil

logger = LogUtil.get_logger(__name__)

class DBClient:
    """ZODB数据库客户端"""
    def __init__(
        self,
        type: Optional[str],
        host: Optional[str],
        port: Optional[int],
        path: Optional[str] = None,
        timeout: Optional[int] = None,
        user: Optional[str] = None,
        password: Optional[str] = None):
        """初始化数据库客户端

        Args:
            name (str): 数据库名称
            db_uri (str): 数据库连接URI
            timeout (int): 超时时间（毫秒）
        """
        # 初始化属性
        self.storage = None
        self.db = None
        self.connection = None
        self.is_open = False
        self.root = None
        match type:
            case 'ZODB':
                self.__init_zodb(host, port, path)
            case _:
                raise ValueError(f"不支持的数据库类型: {type}")

    def __del__(self):
        """销毁数据库客户端"""
        self.destroy()

    def destroy(self):
        if self.is_open:
            self.is_open = False
            try:
                self.flush()
            except:
                logger.error("关闭数据库前flush失败")
        # 安全关闭各个资源，即使它们可能未初始化
        if hasattr(self, 'connection') and self.connection is not None:
            try:
                self.connection.close()
            except:
                logger.error("关闭数据库连接失败")
        if hasattr(self, 'db') and self.db is not None:
            try:
                self.db.close()
            except:
                logger.error("关闭数据库失败")
        if hasattr(self, 'storage') and self.storage is not None:
            try:
                self.storage.close()
            except:
                logger.error("关闭数据库存储失败")

    def __init_zodb(self, host: str, port: int, path: Optional[str] = None):
        logger.debug(f"初始化ZODB客户端: host={host}, port={port}, path={path}")
        # 创建数据库连接
        if host and port and not path:
            self.storage = ClientStorage(host, port)
        elif not host and not port and path:
            self.storage = FileStorage.FileStorage(path)
        else:
            raise ValueError("必须指定host和port或者path")
            
        self.db = DB(self.storage)
        self.connection = self.db.open()
        self.is_open = True
        self.root = self.connection.root()

    def flush(self):
        """将内存中的数据刷新到数据库"""
        try:
            transaction.commit()
        except Exception as e:
            logger.error(f"刷新数据库时发生错误: {e}")
            transaction.abort()
            raise e
    